package com.sojson.util.encrypt.bothway.imparity.rsa;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.springframework.core.io.ClassPathResource;

import com.sojson.constant.Constant;
import com.sojson.util.ExpUtil;
import com.sojson.util.encrypt.bothway.alike.base64.Base64Util;
import com.sojson.util.encrypt.bothway.imparity.bean.CustomKeyPair;
import com.sojson.util.encrypt.enums.EEncryptType;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * RSA双向非对称加密解密工具类
 * 
 * @author liu
 * @date 2020-09-04
 */
@Slf4j
public class RsaUtil {

    /** 加密算法RSA */
    public static final String KEY_ALGORITHM = "RSA";
    /**  */
    public static final String FILL_MODE_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";
    /**  */
    public static final String FILL_MODE_OAEPWITHSHA_1_ANDMGF1PADDING = "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";
    /** 默认填充模式 */
    public static final String FILL_MODE_DEFAULT = FILL_MODE_PKCS1_PADDING;
    /**  */
    public static final String SIGN_TYPE_SHA256WITHRSA = "SHA256WithRSA";
    /** 默认签名类型 */
    public static final String SIGN_TYPE_DEFAULT = SIGN_TYPE_SHA256WITHRSA;
    /** RSA最大加密明文大小 */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /** RSA最大解密密文大小 */
    private static final int MAX_DECRYPT_BLOCK = 128;

    /**
     * 加密
     * 
     * @param data      内容
     * @param publicKey 公钥
     * @return
     * @throws Exception 
     */
    public static String encrypt(String data, String publicKey) throws Exception {
        return encrypt(data, publicKey, FILL_MODE_DEFAULT);
    }

    /**
     * 加密
     * 
     * @param data      内容
     * @param publicKey 公钥
     * @return
     * @throws Exception 
     */
    public static byte[] encrypt(byte[] data, String publicKey) throws Exception {
        return encryptToByte(new String(data), publicKey);
    }

    /**
     * 加密
     * 
     * @param data      内容
     * @param publicKey 公钥
     * @return
     * @throws Exception 
     */
    public static byte[] encryptToByte(String data, String publicKey) throws Exception {
        return encrypt(data, publicKey).getBytes();
    }

    /**
     * 加密
     * 
     * @param data      内容
     * @param publicKey 公钥
     * @return
     * @throws Exception 
     */
    public static String encryptToStr(byte[] data, String publicKey) throws Exception {
        return encrypt(new String(data), publicKey);
    }

    /**
     * 加密
     * 
     * @param data      内容
     * @param publicKey 公钥
     * @param fillMode  填充模式
     * @return
     * @throws Exception 
     */
    private static String encrypt(String data, String publicKey, String fillMode) throws Exception {
        byte[] dataByte = data.getBytes(StandardCharsets.UTF_8);
        byte[] keyBytes = decryptContentToByte(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key key = keyFactory.generatePublic(x509KeySpec);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(fillMode);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        int inputLen = dataByte.length;
        ByteArrayOutputStream out = null;
        byte[] encryptedData = null;
        try {
            out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(dataByte, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(dataByte, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            encryptedData = out.toByteArray();
        } finally {
            try {
                out.close();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return encryptContentToStr(encryptedData);
    }

    /**
     * 加密
     * 
     * @param data      内容
     * @param publicKey 公钥
     * @return
     * @throws Exception
     */
    public static String encrypt(String data, PublicKey publicKey) throws Exception {
        return encrypt(data.getBytes(), publicKey);
    }

    /**
     * 加密
     * 
     * @param data      内容
     * @param publicKey 公钥
     * @return
     * @throws Exception
     */
    public static String encrypt(byte[] data, PublicKey publicKey) throws Exception {
        try {
            Cipher cipher = Cipher.getInstance(FILL_MODE_DEFAULT);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);

            byte[] cipherdata = cipher.doFinal(data);
            return encryptContentToStr(cipherdata);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            ExpUtil.throwEx("当前Java环境不支持RSA v1.5/OAEP");
        } catch (InvalidKeyException e) {
            ExpUtil.throwEx("无效的证书");
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            ExpUtil.throwEx("加密原串的长度不能超过214字节");
        }
        return null;
    }

    /**
     * 解密
     * 
     * @param data          内容
     * @param privateKey    私钥
     * @return
     * @throws Exception 
     */
    public static String decrypt(String data, String privateKey) throws Exception {
        return decrypt(data, privateKey, FILL_MODE_DEFAULT);
    }

    /**
     * 解密
     * 
     * @param data          内容
     * @param privateKey    私钥
     * @return
     * @throws Exception 
     */
    public static byte[] decrypt(byte[] data, String privateKey) throws Exception {
        return decryptToByte(new String(data), privateKey);
    }

    /**
     * 解密
     * 
     * @param data          内容
     * @param privateKey    私钥
     * @return
     * @throws Exception 
     */
    public static byte[] decryptToByte(String data, String privateKey) throws Exception {
        return decrypt(data, privateKey).getBytes();
    }

    /**
     * 解密
     * 
     * @param data          内容
     * @param privateKey    私钥
     * @return
     * @throws Exception 
     */
    public static String decryptToStr(byte[] data, String privateKey) throws Exception {
        return decrypt(new String(data), privateKey);
    }

    /**
     * 解密
     * 
     * @param data          内容
     * @param privateKey    私钥
     * @param fillMode      填充模式
     * @return
     * @throws Exception 
     */
    private static String decrypt(String data, String privateKey, String fillMode) throws Exception {
        byte[] encryptedData = decryptContentToByte(data);
        byte[] keyBytes = decryptContentToByte(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key key = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(fillMode);

        cipher.init(Cipher.DECRYPT_MODE, key);
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = null;
        byte[] decryptedData = null;
        try {
            out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            decryptedData = out.toByteArray();
        } finally {
            try {
                out.close();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return new String(decryptedData);
    }

    /**
     * 私钥解密
     *
     * @param data      内容
     * @param publicKey 公钥
     * @return 解密后的数据
     * @throws Exception 异常信息
     */
    public static String decrypt(String data, PrivateKey privateKey) throws Exception {
        try {
            Cipher cipher = Cipher.getInstance(FILL_MODE_DEFAULT);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] dataByte = decryptContentToByte(data);
            return new String(cipher.doFinal(dataByte), Constant.DEFAULT_ENCODING);
        } catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
            ExpUtil.throwEx("当前Java环境不支持RSA v1.5/OAEP");
        } catch (InvalidKeyException e) {
            ExpUtil.throwEx("无效的私钥");
        } catch (BadPaddingException | IllegalBlockSizeException e) {
            ExpUtil.throwEx("解密失败");
        }
        return null;
    }

    /**
     * 私钥签名
     *
     * @param data          内容
     * @param privateKey    私钥
     * @return
     * @throws Exception
     */
    public static String sign(String data, String privateKey) throws Exception {
        return signToStr(data.getBytes(), privateKey);
    }

    /**
     * 私钥签名
     *
     * @param data          内容
     * @param privateKey    私钥
     * @return
     * @throws Exception
     */
    public static byte[] sign(byte[] data, String privateKey) throws Exception {
        return signToStr(data, privateKey).getBytes();
    }

    /**
     * 私钥签名
     *
     * @param data          内容
     * @param privateKey    私钥
     * @return
     * @throws Exception
     */
    public static byte[] signToByte(String data, String privateKey) throws Exception {
        return sign(data.getBytes(), privateKey);
    }

    /**
     * 私钥签名
     *
     * @param data          内容
     * @param privateKey    私钥
     * @return
     * @throws Exception
     */
    public static String signToStr(byte[] data, String privateKey) throws Exception {
        return sign(data, privateKey, SIGN_TYPE_DEFAULT);
    }

    /**
     * 私钥签名
     *
     * @param data          内容
     * @param privateKey    私钥
     * @param type          私钥
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, String privateKey, String type) throws Exception {
        PKCS8EncodedKeySpec priPkcs8 = new PKCS8EncodedKeySpec(decryptContentToByte(privateKey));
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey priKey = keyFactory.generatePrivate(priPkcs8);
        java.security.Signature signature = java.security.Signature.getInstance(type);

        signature.initSign(priKey);
        signature.update(data);
        byte[] signed = signature.sign();
        return encryptContentToStr(signed);
    }

    /**
     * 私钥签名
     *
     * @param data          内容
     * @param privateKey    私钥
     * @return 加密后的数据
     * @throws Exception 异常信息
     */
    public static String sign(String data, PrivateKey privateKey) throws Exception {
        return sign(data.getBytes(), privateKey);
    }

    /**
     * 私钥签名
     *
     * @param data          内容
     * @param privateKey    私钥
     * @return 加密后的数据
     * @throws Exception 异常信息
     */
    public static String sign(byte[] data, PrivateKey privateKey) throws Exception {
        java.security.Signature signature = java.security.Signature.getInstance(SIGN_TYPE_DEFAULT);
        signature.initSign(privateKey);
        signature.update(data);
        byte[] signed = signature.sign();
        return encryptContentToStr(signed);
    }

    /**
     * 公钥验证签名
     *
     * @param data      内容
     * @param sign      签名
     * @param publicKey 公钥
     * @return 验证结果
     * @throws Exception 异常信息
     */
    public static boolean verify(String data, String sign, String publicKey) throws Exception {
        return verify(data, sign, publicKey, SIGN_TYPE_DEFAULT);
    }

    /**
     * 公钥验证签名
     *
     * @param data      内容
     * @param sign      签名
     * @param publicKey 公钥
     * @return 验证结果
     * @throws Exception 异常信息
     */
    public static boolean verify(byte[] data, byte[] sign, String publicKey) throws Exception {
        return verify(new String(data), new String(sign), publicKey);
    }

    /**
     * 公钥验证签名
     *
     * @param data      内容
     * @param sign      签名
     * @param publicKey 公钥
     * @param type      签名类型
     * @return 验证结果
     * @throws Exception 异常信息
     */
    private static boolean verify(String data, String sign, String publicKey, String type) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance(EEncryptType.RSA.getType());
        byte[] encodedKey = decryptContentToByte(publicKey);
        PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
        java.security.Signature signature = java.security.Signature.getInstance(type);
        signature.initVerify(pubKey);
        signature.update(data.getBytes());
        return signature.verify(decryptContentToByte(sign));
    }

    /**
     * 公钥验证签名
     *
     * @param data      内容
     * @param sign      签名
     * @param publicKey 公钥
     * @return 验证结果
     * @throws Exception 异常信息
     */
    public static boolean verify(String data, String sign, PublicKey publicKey) throws Exception {
        java.security.Signature signature = java.security.Signature.getInstance(SIGN_TYPE_DEFAULT);
        signature.initVerify(publicKey);
        signature.update(data.getBytes());
        return signature.verify(decryptContentToByte(sign));
    }

    /**
     * 加密
     * 
     * @param data      内容
     * @param publicKey 公钥
     * @return
     * @throws Exception 
     */
    public static String encryptContentToStr(byte[] data) {
        return Base64Util.encryptToStr(data);
    }

    /**
     * 解密
     * 
     * @param data          内容
     * @param privateKey    私钥
     * @return
     * @throws Exception 
     */
    public static byte[] decryptContentToByte(String data) {
        return Base64Util.decryptToByte(data);
    }

    /**
     * 从字符串中加载公钥<br>
     * 加载时使用的是PKCS8EncodedKeySpec（PKCS#8编码的Key指令）。
     *
     * @param privateKeyStr 私钥
     * @return {@link PrivateKey}
     * @throws Exception 异常信息
     */
    public static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
        try {
            byte[] buffer = decryptContentToByte(publicKeyStr);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            return keyFactory.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e) {
            ExpUtil.throwEx("无此算法");
        } catch (InvalidKeySpecException e) {
            ExpUtil.throwEx("公钥非法");
        } catch (NullPointerException e) {
            ExpUtil.throwEx("公钥数据为空");
        }
        return null;
    }

    /**
     * 获取公钥
     *
     * @param certPath 平台证书路径
     * @return
     * @throws IOException 
     */
    public static PublicKey getPublicKey(String certPath) throws IOException {
        return getCertificate(certPath).getPublicKey();
    }

    /**
     * 获取公钥
     *
     * @param inputStream 证书文件
     * @return {@link X509Certificate} 获取证书
     * @throws IOException 
     */
    public static PublicKey getPublicKey(InputStream inputStream) throws IOException {
        return getCertificate(inputStream).getPublicKey();
    }

    /**
     * 获取证书序列号
     *
     * @param certPath 平台证书路径
     * @return
     * @throws IOException 
     */
    public static String getSerialNumber(String certPath) throws IOException {
        return getCertificate(certPath).getSerialNumber().toString(16).toUpperCase();
    }

    /**
     * 获取证书序列号
     *
     * @param inputStream 证书文件
     * @return {@link X509Certificate} 获取证书
     * @throws IOException 
     */
    public static String getSerialNumber(InputStream inputStream) throws IOException {
        return getCertificate(inputStream).getSerialNumber().toString(16).toUpperCase();
    }

    /**
     * 获取证书
     *
     * @param certPath 平台证书路径
     * @return
     * @throws IOException 
     */
    public static X509Certificate getCertificate(String certPath) throws IOException {
        return getCertificate(FileUtil.getInputStream(certPath));
    }

    /**
     * 获取证书
     *
     * @param inputStream 证书文件
     * @return {@link X509Certificate} 获取证书
     * @throws IOException 
     */
    private static X509Certificate getCertificate(InputStream inputStream) throws IOException {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate)cf.generateCertificate(inputStream);
            return cert;
        } catch (CertificateExpiredException e) {
            ExpUtil.throwEx("证书已过期");
        } catch (CertificateNotYetValidException e) {
            ExpUtil.throwEx("证书尚未生效");
        } catch (CertificateException e) {
            ExpUtil.throwEx("无效的证书");
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (Exception e2) {
                    log.error(e2.getMessage(), e2);
                }
            }
        }
        return null;
    }

    /**
     * 从字符串中加载私钥<br>
     * 加载时使用的是PKCS8EncodedKeySpec（PKCS#8编码的Key指令）。
     *
     * @param privateKeyStr 私钥
     * @return {@link PrivateKey}
     * @throws Exception 异常信息
     */
    public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception {
        try {
            byte[] buffer = decryptContentToByte(privateKeyStr);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
            KeyFactory keyFactory = KeyFactory.getInstance(EEncryptType.RSA.getType());
            return keyFactory.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException e) {
            ExpUtil.throwEx("无此算法");
        } catch (InvalidKeySpecException e) {
            ExpUtil.throwEx("私钥非法");
        } catch (NullPointerException e) {
            ExpUtil.throwEx("私钥数据为空");
        }
        return null;
    }

    /**
     * 获取商户私钥
     *
     * @param keyPath 商户私钥证书路径
     * @return {@link PrivateKey} 商户私钥
     * @throws Exception 异常信息
     */
    public static PrivateKey getPrivateKey(String keyPath) throws Exception {
        return loadPrivateKey(getPrivateKeyStr(keyPath));
    }

    /**
     * 获取商户私钥字符串
     *
     * @param keyPath 商户私钥证书路径
     * @return {@link String} 商户私钥
     * @throws Exception 异常信息
     */
    public static String getPrivateKeyStr(String keyPath) throws Exception {
        ClassPathResource classPathResource = new ClassPathResource(keyPath);
        InputStream inputStream = null;
        String originalKey = null;
        try {
            inputStream = classPathResource.getInputStream();
            originalKey = IoUtil.read(inputStream, Constant.DEFAULT_ENCODING);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (Exception e2) {
                    log.error(e2.getMessage(), e2);
                }
            }
        }

        String privateKey = originalKey.replace("-----BEGIN PRIVATE KEY-----", "")
            .replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");
        return privateKey;
    }

    /**
     * 获得公私钥对
     * 
     * @return 
     * @throws Exception 
     */
    public static CustomKeyPair generateKeyPair() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        return new CustomKeyPair(publicKey, privateKey);
    }

    // public static void main(String[] args) throws Exception {
    // String publicKey = "MIID3DCCAsSgAwIBAgIUK289+3RuUcxqPyVgfb50fEpin/QwDQYJKoZIhvcNAQEL"
    // + "BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT"
    // + "FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg"
    // + "Q0EwHhcNMjEwNzA3MDgxOTQzWhcNMjYwNzA2MDgxOTQzWjBuMRgwFgYDVQQDDA9U"
    // + "ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl"
    // + "bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpo"
    // + "ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvMEsk1+TGVWWWS0N3"
    // + "QNMRzVI85m0Y+N+E8700ApZAwPkd9+E23WGfJ91n0vfRG0WSfTl5b6qbYYhUq85F"
    // + "eZK3ZlmXYY6NNH9eTo857vG7rNnirbdwz33uT9LT7hglmsDvslL4aF5bVCRr9B1I"
    // + "FqkqJ27oD3BfO0i3Dagv/zTvdid3uDyQyQ+mJZTAhLvD4ByTirht0WukhK8PHnQg"
    // + "Wj/5cDWk7EndFh2aMbhpZ8u6nYBD/mIWM/IC6JGMVizri5Ju538mDow4v2SKUfel"
    // + "CKu8PCoRixY1B3HEjTJbP3aloAZgiQ9YheiFnL6d7Eu8bNLza8atzW8Bi3m5j+Fk"
    // + "38BrAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBlBgNVHR8EXjBc"
    // + "MFqgWKBWhlRodHRwOi8vZXZjYS5pdHJ1cy5jb20uY24vcHVibGljL2l0cnVzY3Js"
    // + "P0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3NTQ5ODQ2QzAxQzNFOEVCRDIwDQYJ"
    // + "KoZIhvcNAQELBQADggEBAKIKoipOV6OYl4pwI5J8twn6Myj1+3c+1DepySyPyPKw"
    // + "kJnbkFT6J7R8/7nj6OEgtL9v0Cdw4Bc2XPaUWPYxfPFAd3U5UGFAhhDJVdeCTyCW"
    // + "Y+uMrpDBxlxsChh95fzVAgwnFP8+toUUYuSWGQR2EyWw/aunVjHi4VjPhY/rKIvQ"
    // + "Mx2iDGYlm+iw8CGeVecbqInSnEVBlcjHy6UFJm00cLnX1+sC++OqB2kbfEIOwXAJ"
    // + "pjg8qDj5PPW9EkQo3U4kKa56p0mzUkw7i85U3MXDBjmF0xfbETfrRjqaQVvaMAvC"
    // + "I+2Mef46tGwMN5ms1UKdFIefibTA5ohbwK0839knplI=";
    // String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCymSDFIPrMWX8C"
    // + "SiYmR1IxgKkUN2NiLiq+BOuQmsjwUcliCeDZFhoKn5DHvpK5hHqmu7kGbgZXiVZa"
    // + "cf4vNO+wcGB6Ysju+Og5+1IXAZOEisdbpOmwo8jQVZ4M21JRzX4nu6Mfnr+0NFGb"
    // + "MobYpqdJ15seHEoORpoiLeeUehlLgRKyIKCf7KMod2xf6Ai/1iz7gKPEf2YQBRZI"
    // + "EQhfzgG3AyaWWDqotcyCuYSIJjCN4rL3vvWB+7eMqI0zJqcRZ6A9VFsUwAn7rOzO"
    // + "osRI3EeAZtjadJnUSscjawwh60ioJPEWILEh0aS/eypCdjG7zF2yxT7xCbyCy01O"
    // + "dh38V5chAgMBAAECggEAcfUlJMNjY+qjEPnxF7Ggb3ex6vVgk6/zk+WdzVoGZtk4"
    // + "zzaQYtQob6ja/6jJBFjUzfiwGbswjsBR+koML2Duo71AwjawEVN/EigbfBSEZSkM"
    // + "BZzXg98t7kkDHR8AirO9EGs4rZ9koP5VJ9r4kdrcmVBaaL8SPcOs66wwvNufsj2r"
    // + "Xa0j/pu5vOvm8MjkLmotXplbSoEtQ9G7yFDPizTGLo+Wk2emcqm8hk7LoWPU3xlY"
    // + "4GiwuceFoSS8ZW1En/MwnM/SAYn5rhFx7yzPFWoNrJMweUG0NemiBEUh1JQRifBC"
    // + "cNfSRIqr4amq+as4vfavP4uzQnXgBL2VHaANObSjMQKBgQDgB+79+9UzpT3ELXns"
    // + "XYjjOcVfnf+H949Yey+CoeoQQX8RrB1eV3mh7mLxsbFrCk77g9Cdf/u9dpTctKmS"
    // + "gZ/DfvVf1aXNfLHUNf/vTVYCWJ8LJS80EvDFWpSXaTNBCGxJYNMG5Ns0O7jbFjp3"
    // + "3p4vQ3X5ZPePZawo4bNLpZMOzQKBgQDMFX1SkWJ7ZCozNYwVfrYlQmEJOMIezE2o"
    // + "VirVS8BkELhWZq5O/CU7hLzSd72/zwvuyMC10S6o/DWoGAWnW45J0uhKeV1mAikQ"
    // + "xMU/bdBKJaN+gyZf+PCDvbaaX4LPsB31S/S2gqYUqNLm4Ll0kaVIKe4qxml4xUyU"
    // + "eqNsWwFBpQKBgQC9troyJrJzG7lkicY33TVwhpmX0Sp1L7UaDqc7DnYx8eTzSDdO"
    // + "jvEXqdHsLre5l28vGn7tAVZjKSoChJMc19w9JyQPVdMkYjYNKPVk5q6xKe709zYz"
    // + "+N4fogc2+QVISyO4N+A8dE0UvIZcMUSuAb0e9RfQbCogKs9Rh1/X7YzM+QKBgHpF"
    // + "scUjZ86nz4TI4zoJpdWi9IJS6DMNksV1gsoyTX1maxsRAARAm4oSWBL9PMlLokmZ"
    // + "K6SDRKJoITmp0tFXUGO4ogXkuumgB7yNN+Rtxap27IKizv4XJvq3Uk0hRj1qtjg+"
    // + "HsquchTUpS9AmrxVeqJGxPQJ1i1OgDhBVeJYj+MlAoGBAIht8I0XcCgAz15Q94RM"
    // + "/GiT3nbrWzW9ETfM7pBMQPmXxifkRNyjRVgu4KS9MobA6wP57MZhtMAl6wYdckLn"
    // + "yffs9+ttahpW4kefpjz3WCCPoMyAUnXAf9preSM+lYbaHLu3x6VUadY6rUL8z6os" + "60BUdnr/7w2FB9dayUHhGw/2";
    // X509Certificate certificate = getCertificate(new FileInputStream(new File(
    // "D:\\develop\\java\\project\\0.local\\ide\\sojson\\sojson-web\\sojson-web-recruit\\sojson-web-recruit-core\\src\\main\\resources\\cert\\apiclient_cert.pem")));
    //
    // PublicKey loadPublicKey = null;
    // PrivateKey loadPrivateKey = null;
    //
    // // loadPublicKey = loadPublicKey(publicKey);
    // loadPrivateKey = loadPrivateKey(privateKey);
    //
    // CustomKeyPair generateKeyPair = generateKeyPair();
    // publicKey = generateKeyPair.getPublicKeyStr();
    // privateKey = generateKeyPair.getPrivateKeyStr();
    //
    // // loadPublicKey = loadPublicKey(publicKey);
    // // loadPrivateKey = loadPrivateKey(privateKey);
    //
    // System.out.println("公钥\r\n" + publicKey);
    // System.out.println("私钥\r\n" + privateKey);
    //
    // String a = "123456";
    // byte[] bytes = a.getBytes();
    //
    // String encrypt1 = encrypt(a, publicKey);
    // byte[] encrypt2 = encrypt(bytes, publicKey);
    // String encrypt3 = encryptToStr(bytes, publicKey);
    // byte[] encrypt4 = encryptToByte(a, publicKey);
    // String encrypt5 = encrypt(a, certificate.getPublicKey());
    // String encrypt6 = encrypt(a, loadPublicKey(publicKey));
    // System.out.println("加密: " + encrypt1);
    // System.out.println("加密: " + new String(encrypt2));
    // System.out.println("加密: " + encrypt3);
    // System.out.println("加密: " + new String(encrypt4));
    //
    // System.out.println("解密: " + decrypt(encrypt1, privateKey));
    // System.out.println("解密: " + new String(decrypt(encrypt2, privateKey)));
    // System.out.println("解密: " + new String(decryptToByte(encrypt3, privateKey)));
    // System.out.println("解密: " + decryptToStr(encrypt4, privateKey));
    // System.out.println("解密: " + decrypt(encrypt5, loadPrivateKey));
    // System.out.println("解密: " + decrypt(encrypt6, loadPrivateKey(privateKey)));
    //
    // String sign1 = sign(a, privateKey);
    // byte[] sign2 = sign(bytes, privateKey);
    // byte[] sign3 = signToByte(a, privateKey);
    // String sign4 = signToStr(bytes, privateKey);
    // String sign5 = sign(a, loadPrivateKey);
    // String sign6 = sign(a, loadPrivateKey(privateKey));
    // System.out.println("签名: " + sign1);
    // System.out.println("签名: " + new String(sign2));
    // System.out.println("签名: " + new String(sign3));
    // System.out.println("签名: " + sign4);
    // System.out.println("签名: " + sign5);
    // boolean signCheck = verify(a, sign1, publicKey);
    // boolean signCheck2 = verify(bytes, sign2, publicKey);
    // boolean signCheck3 = verify(bytes, sign3, publicKey);
    // boolean signCheck4 = verify(a, sign4, publicKey);
    // boolean signCheck5 = verify(a, sign5, certificate.getPublicKey());
    // boolean signCheck6 = verify(a, sign6, loadPublicKey(publicKey));
    // System.out.println("验签: " + signCheck);
    // System.out.println("验签: " + signCheck2);
    // System.out.println("验签: " + signCheck3);
    // System.out.println("验签: " + signCheck4);
    // System.out.println("验签: " + signCheck5);
    // System.out.println("验签: " + signCheck6);
    // }

}